#include "QiliSubtitleEmoji.h"

#include <QResource>
#include <QPixmap>
#include <QNetworkAccessManager>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QCryptographicHash>
#include <QFile>
#include <QEventLoop>

Q_GLOBAL_STATIC(QNetworkAccessManager, EmojiDownloader);

QMutex                  QiliSubtitleEmoji::mMutex  = QMutex();
QMap<QString, QString>  QiliSubtitleEmoji::mCaches = QMap<QString, QString>();

QString QiliSubtitleEmoji::load(const QString &url)
{
    auto md5 = QCryptographicHash::hash(url.toUtf8(), QCryptographicHash::Md5);
    auto cached = QString("/home/loong/emoji-%1.qili.img").arg(md5);
    if (isCached(md5)) {
        return cached;
    }

    auto *reply = EmojiDownloader->get(QNetworkRequest(url));
    QObject::connect(reply, &QNetworkReply::finished, [reply, md5, cached]{
        reply->deleteLater();

        if (reply->error() != QNetworkReply::NoError) {
            return;
        }

        auto data = reply->readAll();
        QFile file(cached);
        auto openned = file.open(QFile::ReadWrite);
        if (openned) {
            cache(md5, cached, [&file, &data]{
                file.write(data);
                return true;
            });
        }
        file.close();
    });
    QObject::connect(reply, &QNetworkReply::errorOccurred, [reply](auto error){
        reply->deleteLater();
        mMutex.unlock();
    });
    QEventLoop replyWaiter;
    QObject::connect(reply, &QNetworkReply::finished, &replyWaiter, &QEventLoop::quit);
    QObject::connect(reply, &QNetworkReply::errorOccurred, &replyWaiter, &QEventLoop::quit);
    replyWaiter.exec(QEventLoop::ExcludeUserInputEvents);
    return cached;
}

bool QiliSubtitleEmoji::isCached(const QString &digest)
{
    mMutex.lock();
    if (mCaches.contains(digest)) {
        mMutex.unlock();
        return true;
    }
    mMutex.unlock();
    return false;
}

void QiliSubtitleEmoji::cache(const QString &digest, const QString &cached, std::function<bool()> persister)
{
    mMutex.lock();
    if (mCaches.contains(digest)) {
        mMutex.unlock();
        return;
    }
    bool successful = persister();
    if (successful) {
        mCaches[digest] = cached;
    }
    mMutex.unlock();
}

